(function() {
    Nokia.Accordion = Nokia.Widget.extend({
        initialize: function(options) {
            var instance = this;

			var defaults = {
				event: 'click',
				header: '> li > :first-child,> :not(li):even',
				icons: {
					header: "ui-icon-triangle-1-e",
					headerSelected: "ui-icon-triangle-1-s"
				},
				multiple: true,
				collapsible: true,
				closed: false
            };

            instance.options = jQuery.extend(defaults, options);

            instance._super.apply(instance, [instance.options]);

			instance.registerData("accordion");

			instance._applyStyle();

			instance._attachEvents();

			instance.registerVibrationOn([ 'toggle' ]);

			instance.fireCallback('create');
        },

		_attachEvents: function() {
			var instance = this;
			var element = instance.element;
			var options = instance.options;

			instance.headers.unbind('mousedown.accordion');
			instance.headers.unbind('keypress.accordion');

			instance.headers.bind('focus.accordion', function() {
				var active = jQuery(this).next().is(':visible');

				if (active) {
					jQuery(this).removeClass([instance.Styles.stateActive].join(' '));
				}

				jQuery(this).addClass([instance.Styles.stateHover].join(' '));
			});

			instance.headers.bind('blur.accordion', function() {
				var active = jQuery(this).next().is(':visible');

				if (active) {
					jQuery(this).addClass([instance.Styles.stateActive].join(' '));
				} else {
					jQuery(this).addClass([instance.Styles.stateDefault].join(' '));
				}

				jQuery(this).removeClass([instance.Styles.stateHover].join(' '));
			});

			instance.headers.hover(function() {
				jQuery(this).trigger('focus.accordion');
			}, function() {
				jQuery(this).trigger('blur.accordion');
			});

			instance.headers.bind('click.accordion', function(event) {
				instance.toggle(this, event);
			});

			Nokia.util.bindEnter(instance.headers, function(event) {
				instance.toggle(this, event);
			});
		},

		toggleClass: function(className, classe) {
			var hasClass = className.indexOf(classe) > -1, outClass;

			if (hasClass) {
				outClass = className.replace(classe, '');
			}
			else {
				outClass = [className, classe].join(' ');
			}

			return outClass;
		},

		toggle: function(index, event) {
			var instance = this;
			var header = instance._findActive(index);
			var headerEl = header[0];
			var content = header.next();
			var contentEl = content[0];
			var options = instance.options;
			var headerActive = content.is(':visible');

			if (headerActive && (options.collapsible == false)) {
				if (instance.getActiveContents().length == 1) {
					return false;
				}
			}

			if (options.multiple == false) {
				var activeContentsBefore = instance.closeAll();

				if (headerActive && activeContentsBefore.length == 1) {
					return false;
				}
			}

			var icon = header.find(".ui-icon");
			var iconEl = icon[0];

			if (!headerActive) {
				iconEl.className = [ 'ui-icon', options.icons.headerSelected ].join(' ');
			}
			else {
				iconEl.className = [ 'ui-icon', options.icons.header ].join(' ');
			}

			contentEl.className = instance.toggleClass(
				contentEl.className, instance.Styles.accordionContentActive
			);

			if (!header.hasClass(instance.Styles.stateHover)) {

				headerEl.className = instance.toggleClass(
					headerEl.className, instance.Styles.stateActive
				);

				headerEl.className = instance.toggleClass(
					headerEl.className, instance.Styles.stateDefault
				);

			}

			var callbackType = headerActive ? 'close' : 'open';

			instance.fireCallback(callbackType, event, header, content);
			instance.fireCallback('toggle', event, header, content);
		},

		closeAll: function() {
			var instance = this;
			var options = instance.options;
			var activeHeaders = instance.getActiveHeaders();
			var activeContents = activeHeaders.next();
			var icon = activeHeaders.find(".ui-icon");

			for (var i = 0; i < activeHeaders.length; i++) {
				activeHeaders[i].className = [
					instance.Styles.stateDefault,
					instance.Styles.cornerAll,
					instance.Styles.helperReset,
					instance.Styles.accordionHeader
				].join(' ');

				activeContents[i].className = [
					instance.Styles.accordionContent,
					instance.Styles.helperReset,
					instance.Styles.widgetContent,
					instance.Styles.cornerBottom
				].join(' ');

				icon[i].className = [options.icons.header, 'ui-icon'].join(' ');
			}

			return activeContents;
		},

		getActiveContents: function() {
			var instance = this;
			return instance.contents.filter('.' + instance.Styles.accordionContentActive);
		},

		getActiveHeaders: function() {
			var instance = this;
			return instance.headers.filter('.' + instance.Styles.stateActive);
		},

		_findActive: function(selector) {
			var instance = this;
			var active = null;
			var headers = instance.headers;

			if (selector) {
				if (typeof selector == "number") {
					active = headers.filter(":eq(" + selector + ")");
				}
				else {
					active = headers.not(headers.not(selector));
				}
			}
			else {
				if (selector === false) {
					active = jQuery([]);
				}
				else {
					active = headers.filter(":eq(0)");
				}
			}

			return active;
		},

		_applyStyle: function() {
			var instance = this;
			var element = instance.element;
			var options = instance.options;

			element.addClass([instance.Styles.accordion, instance.Styles.widget, instance.Styles.helperReset].join(' '));

			// need to mark top-LIs in a UL-accordion for some IE-fix
			if (element[0].nodeName.toLowerCase() == "ul") {
				var children = element.children("li")
				children.addClass(instance.Styles.accordionLIFix);
			}

			instance.headers = element.find(options.header);
			var headers = instance.headers;
			headers.addClass([instance.Styles.accordionHeader, instance.Styles.helperReset, instance.Styles.stateDefault, instance.Styles.cornerAll].join(' '));

			var content = headers.next();
			content.addClass([instance.Styles.accordionContent, instance.Styles.helperReset, instance.Styles.widgetContent, instance.Styles.cornerBottom].join(' '));

			var active = this._findActive(instance.active || options.active);
			active.addClass(instance.Styles.cornerAll);
			active.toggleClass(instance.Styles.cornerTop);

			//Append icon elements
			instance.headers.each(function() {
				var header = this;
				var icon = Nokia.dom.parseHTML('<span class="ui-icon ' + options.icons.header + '"></span>');

				Nokia.dom.prepend(header, icon);
			});
			//icon.prependTo(this.headers);

			instance.contents = instance.headers.next();

			if (!options.closed || !options.collapsible) {
				active.toggleClass(instance.Styles.stateDefault);
				active.toggleClass(instance.Styles.stateActive);
				active.next().addClass(instance.Styles.accordionContentActive);

				var uiIcon = active.find(".ui-icon");
				uiIcon.toggleClass(options.icons.header);
				uiIcon.toggleClass(options.icons.headerSelected);
			}
		},

		Styles: {
			accordion: 'ui-accordion',
			accordionContent: 'ui-accordion-content',
			accordionContentActive: 'ui-accordion-content-active',
			accordionHeader: 'ui-accordion-header',
			accordionLIFix: 'ui-accordion-li-fix',
			cornerAll: 'ui-corner-all',
			cornerBottom: 'ui-corner-bottom',
			cornerTop: 'ui-corner-top',
			helperReset: 'ui-helper-reset',
			stateActive: 'ui-state-active',
			stateDefault: 'ui-state-default',
			stateHover: 'ui-state-hover',
			widget: 'ui-widget',
			widgetContent: 'ui-widget-content'
		}
    });
})();